package com.zonhar.autofeed.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pi4j.io.gpio.RaspiPin;
import com.zonhar.autofeed.common.device.i2c.PcaTask;
import com.zonhar.autofeed.common.enums.FeedTypeEnum;
import com.zonhar.autofeed.common.config.AppConfig;
import com.zonhar.autofeed.dao.AutoFeedWeightDao;
import com.zonhar.autofeed.common.device.dht.Data;
import com.zonhar.autofeed.common.device.dht.Dht11Device;
import com.zonhar.autofeed.common.device.i2c.Pca9685DeviceUtils;
import com.zonhar.autofeed.entities.dto.QueryPageDto;
import com.zonhar.autofeed.entities.entity.AutoFeedWeightEntity;
import com.zonhar.autofeed.entities.entity.DistConfigEntity;
import com.zonhar.autofeed.entities.entity.SensorEntity;
import com.zonhar.autofeed.common.exception.RaspberrypiException;
import com.zonhar.autofeed.service.AutoFeedWeightService;
import com.zonhar.autofeed.service.DistConfigService;
import com.zonhar.autofeed.service.SensorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zonhar
 */
@Service
public class AutoFeedWeightServiceImpl extends ServiceImpl<AutoFeedWeightDao, AutoFeedWeightEntity> implements AutoFeedWeightService {

    private final static Logger log = LoggerFactory.getLogger(AutoFeedWeightServiceImpl.class);

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private DistConfigService distConfigService;

    @Autowired
    private SensorService sensorService;

    @Autowired
    private PcaTask pcaTask;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AutoFeedWeightEntity saveInfo(FeedTypeEnum feedTypeEnum, long weight, Integer releaseNum) {
        QueryWrapper<SensorEntity> sensorEntityQueryWrapper =new QueryWrapper<>();
        sensorEntityQueryWrapper.eq("id",3);
        SensorEntity sensorEntity = sensorService.getOne(sensorEntityQueryWrapper);
        if(sensorEntity.getStat().equals(1) || sensorEntity.getStat().equals(2)){
            throw new RaspberrypiException("舵机" + (sensorEntity.getStat().equals(1) ? "已停用" : "异常"));
        }
        AutoFeedWeightEntity autoFeedWeightEntity = new AutoFeedWeightEntity();
        //重量
        autoFeedWeightEntity.setWeight(new BigDecimal(weight));
        autoFeedWeightEntity.setCreateDate(new Date());
        autoFeedWeightEntity.setType(feedTypeEnum.getCode());
        autoFeedWeightEntity.setTypeName(feedTypeEnum.getDesc());
        //投放次数
        autoFeedWeightEntity.setReleaseNum(releaseNum);
        this.save(autoFeedWeightEntity);

        //驱动放粮
        pcaTask.releaseFeed(releaseNum);

        return autoFeedWeightEntity;
    }

    private boolean getSenor(Long id){
        QueryWrapper<SensorEntity> sensorEntityQueryWrapper =new QueryWrapper<>();
        sensorEntityQueryWrapper.eq("id",id);
        SensorEntity sensorEntity = sensorService.getOne(sensorEntityQueryWrapper);
        return sensorEntity.getStat().equals(0);
    }



    @Override
    public Map<String, Object> getHeadStatusData() {
        Map<String, Object> params = MapUtil.newHashMap();
        if (getSenor(2L)) {
            //params.put("weight", RpiDeviceUtils.getHx711Weight());
            Data datas = Dht11Device.getDht11Data(RaspiPin.GPIO_07);
            JSONObject data =new JSONObject();
            data.put("celsius",datas.getCelsius().setScale(0, RoundingMode.HALF_UP)+" °c");
            data.put("humidity",datas.getHumidity().setScale(0, RoundingMode.HALF_UP)+"%RH");
            data.put("fahrenheit",datas.getFahrenheit().setScale(0, RoundingMode.HALF_UP));
            params.put("dhtData", data);
        } else {
            JSONObject data =new JSONObject();
            data.put("celsius","停用");
            data.put("humidity","停用");
            data.put("fahrenheit","停用");
            params.put("dhtData", data);
        }

        Integer feedCocnt = this.getBaseMapper().getFeedCount();
        params.put("releaseNum", feedCocnt);
        params.put("isAutoFeed", appConfig.isAutoFeed ? "是" : "否");
        return params;
    }

    @Override
    public Page<AutoFeedWeightEntity> queryPage(QueryPageDto queryPageDto) {
        QueryWrapper<AutoFeedWeightEntity> queryWrapper = new QueryWrapper<>();

        String keyword = queryPageDto.getKeyword();
        if (!StrUtil.isBlankIfStr(keyword)) {
            queryWrapper.like("type_name", keyword).or().like("release_num", keyword);
        }

        queryWrapper.orderByDesc("create_date");
        Integer pageNo = Objects.isNull(queryPageDto.getPageNo()) ? 1 : queryPageDto.getPageNo();
        Integer pageSize = Objects.isNull(queryPageDto.getPageSize()) ? 10 : queryPageDto.getPageSize();
        Page<AutoFeedWeightEntity> pageInfo = new Page<>(pageNo, pageSize);
        Page<AutoFeedWeightEntity> page = this.page(pageInfo, queryWrapper);
        List<AutoFeedWeightEntity> records = page.getRecords();
        if (!CollectionUtils.isEmpty(records) && records.size() > 0) {
            records = records.stream().map(autoFeedWeightEntity -> {
                Date createDate = autoFeedWeightEntity.getCreateDate();
                autoFeedWeightEntity.setYear(DateUtil.format(createDate, "yyyy"));
                autoFeedWeightEntity.setTime(DateUtil.format(createDate, "hh:mm"));
                return autoFeedWeightEntity;
            }).collect(Collectors.toList());
            page.setRecords(records);
        }
        return page;
    }

    @Override
    public Map<String, Object> getDashBoard() {
        Map<String, Object> params = MapUtil.newHashMap();
        List<String> weekChList = new ArrayList<>();
        List<BigDecimal> autoFeedLine = new ArrayList<>();
        List<BigDecimal> releaseNumLine = new ArrayList<>();
        //获取本周的数据
        List<Date> dates = com.zonhar.autofeed.common.util.DateUtil.dateToWeek(new Date());

        Map<String, List<AutoFeedWeightEntity>> calcData = getCalcData(dates);

        for (Date weekDate : dates) {
            weekChList.add(com.zonhar.autofeed.common.util.DateUtil.getWeek(weekDate));
            String week = DateUtil.format(weekDate, "yyyy-MM-dd");
            if (calcData == null) {
                autoFeedLine.add(BigDecimal.ZERO);
                releaseNumLine.add(BigDecimal.ZERO);
                continue;
            }
            List<AutoFeedWeightEntity> autoFeedWeightEntities = calcData.get(week);
            if (CollectionUtils.isEmpty(autoFeedWeightEntities)) {
                autoFeedLine.add(BigDecimal.ZERO);
                releaseNumLine.add(BigDecimal.ZERO);
                continue;
            }
            //当天累计投食重量
            BigDecimal weight = autoFeedWeightEntities.stream().map(AutoFeedWeightEntity::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal releaseNum = autoFeedWeightEntities.stream().map(autoFeedWeightEntity -> BigDecimal.valueOf(autoFeedWeightEntity.getReleaseNum())).reduce(BigDecimal.ZERO, BigDecimal::add);
            autoFeedLine.add(weight);
            releaseNumLine.add(releaseNum);
        }
        params.put("weekChList", weekChList);
        params.put("autoFeedLine", autoFeedLine);
        params.put("releaseNumLine", releaseNumLine);
        return params;
    }

    private Map<String, List<AutoFeedWeightEntity>> getCalcData(List<Date> dates) {
        QueryWrapper<AutoFeedWeightEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("type", FeedTypeEnum.AUTO_FEED.getCode(), FeedTypeEnum.SD_FEED.getCode());
        queryWrapper.between("create_date",
                DateUtil.format(dates.get(0), "yyyy-MM-dd") + " 00:00:00",
                DateUtil.format(dates.get(dates.size() - 1), "yyyy-MM-dd") + " 23:59:59");
        List<AutoFeedWeightEntity> autoFeedWeightEntities = list(queryWrapper);
        if (CollectionUtils.isEmpty(autoFeedWeightEntities)) {
            return null;
        }
        Map<String, List<AutoFeedWeightEntity>> collect = autoFeedWeightEntities.stream().collect(Collectors.groupingBy(autoFeedWeightEntity -> DateUtil.format(autoFeedWeightEntity.getCreateDate(), "yyyy-MM-dd")));
        return collect;
    }



    /**
     * 获取定时开关
     *
     * @return
     */
    private Boolean getAutoFeedSwitch() {
        QueryWrapper<DistConfigEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dist_name", "cron");
        queryWrapper.eq("dist_group", "params");
        DistConfigEntity configEntity = distConfigService.getOne(queryWrapper);
        return Boolean.valueOf(configEntity.getDistValue());
    }
}
